<template>
  <div class="yd-lightbox-view">
    <lightbox-tip></lightbox-tip>

    <div class="yd-lightbox"
         :style="bgStyleObject">
      <div class="yd-lightbox-head"
           :class="show ? '' : 'yd-lightbox-up-hide'">
        <span>{{currentIndex + 1}} / {{imgItems.length}}</span>
        <a href="javascript:;"
           @click="close">{{closeText}}</a>
      </div>
      <div class="yd-lightbox-img"
           @click="show = !show"
           ref="imgbox"
           :style="dragStyleObject">
        <slider autoplay="0"
                :show-pagination="false"
                :loop="false"
                :callback="changeIndex"
                :index="index">
          <slider-item v-for="(item, key) in imgItems"
                       :key="key">
            <img :src="getImgSrc(item.$el)"
                 style="background-color: #000">
          </slider-item>
        </slider>
        <div class="yd-lightbox-loading"
             v-show="showLoaingIcon">
          <svg width="100%"
               height="100%"
               xmlns="http://www.w3.org/2000/svg"
               viewBox="0 0 100 100"
               preserveAspectRatio="xMidYMid">
            <circle cx="50"
                    cy="50"
                    fill="none"
                    stroke="#ffffff"
                    stroke-width="7"
                    r="47"
                    stroke-dasharray="221.48228207808043 75.82742735936014"
                    transform="rotate(25.5138 50 50)">
              <animateTransform attributeName="transform"
                                type="rotate"
                                calcMode="linear"
                                values="0 50 50;360 50 50"
                                keyTimes="0;1"
                                dur="0.8s"
                                begin="0s"
                                repeatCount="indefinite"></animateTransform>
            </circle>
          </svg>
        </div>
      </div>
      <div class="yd-lightbox-foot"
           :class="show ? '' : 'yd-lightbox-down-hide'"
           v-if="!!txtHTML"
           v-html="txtHTML"></div>
    </div>
  </div>
</template>

<script type="text/babel">
import Slider from '../../slider/src/slider.vue';
import SliderItem from '../../slider/src/slider-item.vue';
import LightboxTip from './lightbox-tip.vue';

export default {
  components: {
    slider: Slider,
    sliderItem: SliderItem,
    lightboxTip: LightboxTip
  },
  data() {
    return {
      index: 1,
      imgItems: [],
      show: true,
      tmpShow: true,
      txtHTML: '',
      closeText: '',
      showLoaingIcon: false,
      touches: {
        speed: 333,
        startX: 0,
        startY: 0,
        moveOffset: 0,
        touchStartTime: 0,
        isDarging: false,
        isRollBack: false
      },
      bgStyleObject: {
        backgroundColor: 'rgba(0, 0, 0, 1)'
      },
      dragStyleObject: {}
    };
  },
  methods: {
    close() {
      this.show = false;

      const touches = this.touches;
      const transform = this.getTransform();

      this.setTranslate(touches.speed, transform.x, transform.y, 0, transform.scale);

      setTimeout(() => {
        this.$el.parentNode && this.$el.parentNode.removeChild(this.$el);
        this.show = true;
        touches.isRollBack = false;
      }, touches.speed);
    },
    changeIndex(index) {
      this.currentIndex = index;
    },
    getImgSrc(el) {
      return el.getAttribute('original') || el.getAttribute('src');
    },
    touchStartHandler(event) {
      const touches = this.touches;

      if (touches.isDarging || this.isRollBack) return;

      touches.startX = event.touches ? event.touches[0].clientX : event.clientX;
      touches.startY = event.touches ? event.touches[0].clientY : event.clientY;

      touches.touchStartTime = Date.now();
    },
    touchMoveHandler(event) {
      event.preventDefault();

      const touches = this.touches;

      if (touches.isRollBack) return;

      const currentY = event.touches ? event.touches[0].clientY : event.clientY;
      const currentX = event.touches ? event.touches[0].clientX : event.clientX;

      const touchAngle =
        (Math.atan2(Math.abs(currentY - touches.startY), Math.abs(currentX - touches.startX)) * 180) / Math.PI;
      const deltaSlide = (touches.moveOffset = currentY - touches.startY);

      if (touchAngle > 60 && deltaSlide > 0) {
        if (!touches.isDarging) {
          this.tmpShow = this.show;
          this.show = false;
        }
        const maxMoveOffset = document.body.offsetHeight / 10;
        this.setTranslate(0, 0, deltaSlide, 1 - deltaSlide / 5 / maxMoveOffset, 1);
        touches.isDarging = true;
      }
    },
    touchEndHandler() {
      const touches = this.touches;

      if (touches.isDarging) {
        const warpperSize = document.body.offsetHeight;
        const timeDiff = Date.now() - touches.touchStartTime;

        touches.isRollBack = true;

        if (timeDiff <= 200 || Math.abs(touches.moveOffset) >= warpperSize * 0.2) {
          this.close();
          return;
        }

        this.setTranslate(touches.speed, 0, 0, 1, 1);
        setTimeout(() => {
          this.setTranslate(0, 0, 0, 1, 1);
          touches.isDarging = false;

          if (this.tmpShow) {
            this.show = true;
          }
          touches.isRollBack = false;
        }, touches.speed);
      }
    },
    getTransform() {
      const body = document.body;
      const curImg = this.imgItems[this.currentIndex];
      const x = -(body.offsetWidth / 2 - curImg.$el.offsetWidth / 2 - curImg.$el.getBoundingClientRect().left);
      const y = -(body.offsetHeight / 2 - curImg.$el.offsetHeight / 2 - curImg.$el.getBoundingClientRect().top);
      const scale = curImg.$el.offsetWidth / body.offsetWidth;

      return {
        x,
        y,
        scale
      };
    },
    setTranslate(speed, translateX, translateY, opacity, scale) {
      this.dragStyleObject.transitionDuration = speed + 'ms';
      this.dragStyleObject.transform =
        'translate3d(' + translateX + 'px, ' + translateY + 'px, 0) scale(' + scale + ')';
      this.bgStyleObject.backgroundColor = 'rgba(0, 0, 0, ' + opacity + ')';
    },
    bindEvent() {
      this.$refs.imgbox.addEventListener('touchstart', this.touchStartHandler);
      this.$refs.imgbox.addEventListener('touchmove', this.touchMoveHandler);
      this.$refs.imgbox.addEventListener('touchend', this.touchEndHandler);
    },
    unBindEvent() {
      this.$refs.imgbox.removeEventListener('touchstart', this.touchStartHandler);
      this.$refs.imgbox.removeEventListener('touchmove', this.touchMoveHandler);
      this.$refs.imgbox.removeEventListener('touchend', this.touchEndHandler);
    }
  },
  created() {
    const transform = this.getTransform();

    this.dragStyleObject.transitionDuration = '0ms';
    this.dragStyleObject.transform =
      'translate3d(' + transform.x + 'px, ' + transform.y + 'px, 0) scale(' + transform.scale + ')';
    this.bgStyleObject.backgroundColor = 'rgba(0, 0, 0, 0)';
  },
  mounted() {
    this.$nextTick(() => {
      this.bindEvent();

      const speed = this.touches.speed;

      this.dragStyleObject.transitionDuration = speed + 'ms';
      this.dragStyleObject.transform = 'translate3d(0px, 0px, 0) scale(1)';
      this.bgStyleObject.backgroundColor = 'rgba(0, 0, 0, 1)';

      setTimeout(() => {
        this.showLoaingIcon = true;
      }, speed);
    });
  },
  beforeDestroy() {
    this.unBindEvent();
  }
};
</script>
